﻿using Elsa.JavaScript.Models;
using Elsa.Workflows;
using Elsa.Workflows.Memory;
using Elsa.Workflows.Models;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using T.FAS.Runtime.MF.Activities.Helper;
using T.FAS.Runtime.MF.Entity;
using T.FAS.Runtime.MF.SPI;
using ElsaExpression = Elsa.Expressions.Models.Expression;

namespace T.FAS.Runtime.MF.Activities.Nodes
{
    internal class DataQueryNode : NodeBase, INodeMapper
    {
        [JsonProperty("data")]
        public new DataQueryNodeData Data { get; set; }
        public List<Variable> Variables { get; set; } = new List<Variable>();
        public List<OutputDefinition> Outputs { get; set; }
        public List<InputDefinition> Inputs { get; set; } = new List<InputDefinition>();
        public IActivity MapToActivity()
        {
            var activity = new DataQueryActivity() { Id = Id, Name = Data.Label };

            activity.DataQueryName = Data.DataQueryName;
            var activityOutputVariables = new Dictionary<string, Variable>();
            //将节点的输出变量，放到elsa的变量列表中
            foreach (var varItem in (Data.OutputVariables ?? new List<UserVariable>()))
            {
                SetVariableInfo(varItem);
                var variable = VariableHelper.GenerateVariable(varItem);
                Variables.Add(variable);
                activityOutputVariables.Add(varItem.VariableName,variable);

                //为了向迭代节点返回值，此处特意增加一个变量，用于处理节点的返回值数组
                var iterationResultVarItem = new UserVariable() { CompositeVarName = $"{varItem.CompositeVarName}{MFConst.IterationResultVariableSuffix}", Type = varItem.ValueType };
                var iterationResultVar = VariableHelper.GenerateVariable(iterationResultVarItem);
                Variables.Add(iterationResultVar);

            }
            //处理入参
            ProcessParamList(activity);

            activity.OutputVariables = activityOutputVariables;

            return activity;
        }
        private void ProcessParamList(DataQueryActivity activity)
        {
            var paramList = Data.parameterValues;

            if (paramList == null || paramList.Count() <= 0) return;

            activity.ParamList = new List<BranchCondition>();
            paramList = paramList.OrderBy(t => t.Sort).ToList();
            foreach (var item in paramList)
            {
                object paramValue = "";

                if (item.Assignment.ValueType == "constant")
                {
                    var parameterValue = VariableHelper.ConvertConstantValue(item.DataType, item.Assignment.ConstantValue);
                    activity.ParamList.Add(new BranchCondition { Label = item.Code, Condition = ElsaExpression.LiteralExpression(parameterValue) });
                }
                else if (item.Assignment.ValueType.ToLower() == "variable")
                {
                    if (string.IsNullOrEmpty(item.Assignment.VariableValue))
                    {
                        activity.ParamList.Add(new BranchCondition { Label = item.Code, Condition = ElsaExpression.LiteralExpression("") });
                    }
                    else
                    {
                        if (item.Assignment.VariableNodeID.StartsWith("iteration"))
                        {
                            if (item.Assignment.VariableValue == "item")
                            {
                                item.Assignment.VariableValue = "CurrentValue";
                            }
                            else if (item.Assignment.VariableValue == "index")
                            {
                                item.Assignment.VariableValue = "CurrentIndex";
                            }
                        }

                        item.Assignment.VariableValue = ActivityHelper.GetSourceVariableRealName(this, item.Assignment.VariableValue, item.Assignment.VariableNodeID);
                        var expression = ActivityHelper.GetVariableExpression(item.Assignment.VariableValue, item.DataType,false);
                        activity.ParamList.Add(new BranchCondition { Label = item.Code, Condition = JavaScriptExpression.Create(expression) });

                    }
                }
            }
        }


        public override List<UserVariable> NodeInputOutputVariables
        {
            get
            {
                if (Data.OutputVariables == null) return new List<UserVariable>();
                Data.OutputVariables.ForEach(v =>
                {
                    SetVariableInfo(v);
                });
                return Data.OutputVariables;
            }
        }

        private void SetVariableInfo(UserVariable v)
        {
            if (string.IsNullOrEmpty(v.ActivityID))
            {
                v.ActivityID = Id;
                v.CompositeVarName = $"{Id}:{v.VariableName}";
                v.CompositeVarName = v.CompositeVarName.Replace("-", "").Replace(":", "");
            }

        }
    }

    public class DataQueryNodeData
    {
        [JsonProperty("label")]
        public string Label { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }

        [JsonProperty("dataQueryId")]
        public string DataQueryID { get; set; }
        [JsonProperty("dataQueryName")]
        public string DataQueryName { get; set; }

        [JsonProperty("parameterValues")]
        public List<ParameterNode> parameterValues { get; set; }

        [JsonProperty("outputFields")]
        public List<UserVariable> OutputVariables { get; set; }
    }

    public class ParameterNode
    {
        [JsonProperty("Code")]
        public string Code { get; set; }

        [JsonProperty("Name")]
        public string Name { get; set; }

        [JsonProperty("ParamType")]
        public string DataType { get; set; }

        [JsonProperty("IsAllowNull")]
        public bool IsAllowNull { get; set; }
        [JsonProperty("Sort")]
        public int  Sort { get; set; }
        [JsonProperty("IsDefault")]
        public string IsDefault { get; set; }
        [JsonProperty("assignment")]
        public AssignmentNode Assignment { get; set; }

    }
    public class AssignmentNode
    {
        [JsonProperty("valueType")]
        public string ValueType { get; set; }

        [JsonProperty("constantValue")]
        public string ConstantValue { get; set; }

        [JsonProperty("variableId")]
        public string VariableID { get; set; }

        [JsonProperty("variableNodeId")]
        public string VariableNodeID { get; set; }

        [JsonProperty("variableValue")]
        public string VariableValue { get; set; }

        [JsonProperty("variableValueId")]
        public string VariableValueID { get; set; }
    }

}
